﻿using System;

namespace DatabaseStuff
{
    /// <summary>
    /// Represents the type of data for one field in a database schema
    /// </summary>
    public sealed class DBDataType
    {
        private enum EnumeratedType
        {
            CHAR,
            STRING,
            INT32,
            DOUBLE,
            DECIMAL,
            AUTO_INT,
            DATE_TIME
        }

        public static readonly DBDataType Char = new DBDataType(EnumeratedType.CHAR);
        public static readonly DBDataType String = new DBDataType(EnumeratedType.STRING);
        public static readonly DBDataType Int32 = new DBDataType(EnumeratedType.INT32);
        public static readonly DBDataType Double = new DBDataType(EnumeratedType.DOUBLE);
        public static readonly DBDataType Decimal = new DBDataType(EnumeratedType.DECIMAL);
        public static readonly DBDataType AutoInt = new DBDataType(EnumeratedType.AUTO_INT);
        public static readonly DBDataType DateTime = new DBDataType(EnumeratedType.DATE_TIME);

        private EnumeratedType datatype;

        private DBDataType(EnumeratedType _datatype)
        {
            datatype = _datatype;
        }

        public static object ParseObject(string obj, DBDataType type)
        {
            char parsedChar;
            System.DateTime parsedDateTime;
            decimal parsedDecimal;
            double parsedDouble;
            int parsedInt;

            switch (type.datatype)
            {
                case DBDataType.EnumeratedType.AUTO_INT:
                    goto case DBDataType.EnumeratedType.INT32;

                case DBDataType.EnumeratedType.CHAR:
                    parsedChar = System.Char.Parse(obj);
                    return parsedChar;

                case DBDataType.EnumeratedType.DATE_TIME:
                    parsedDateTime = System.DateTime.Parse(obj);
                    return parsedDateTime;

                case DBDataType.EnumeratedType.DECIMAL:
                    parsedDecimal = System.Decimal.Parse(obj);
                    return parsedDecimal;

                case DBDataType.EnumeratedType.DOUBLE:
                    parsedDouble = System.Double.Parse(obj);
                    return parsedDouble;

                case DBDataType.EnumeratedType.INT32:
                    parsedInt = System.Int32.Parse(obj);
                    return parsedInt;

                case DBDataType.EnumeratedType.STRING:
                    return obj;

                default:
                    throw new NotSupportedException("This class does not support the supplied type of data");
            }
        }

        public static bool TryParse(string str, out DBDataType dest)
        {
            try
            {
                dest = Parse(str);
            }
            catch (FormatException)
            {
                dest = null;
                return false;
            }

            return true;
        }

        public static DBDataType Parse(string str)
        {
            if (str.Equals(DBDataType.String.ToString()))
                return DBDataType.String;
            else if (str.Equals(DBDataType.Int32.ToString()))
                return DBDataType.Int32;
            else if (str.Equals(DBDataType.AutoInt.ToString()))
                return DBDataType.AutoInt;
            else if (str.Equals(DBDataType.DateTime.ToString()))
                return DBDataType.DateTime;
            else if (str.Equals(DBDataType.Char.ToString()))
                return DBDataType.Char;
            else if (str.Equals(DBDataType.Decimal.ToString()))
                return DBDataType.Decimal;
            else if (str.Equals(DBDataType.Double.ToString()))
                return DBDataType.Double;
            else
                throw new FormatException("Failed to parse a DBDataType from the supplied string");
        }

        public override string ToString()
        {
            string result;

            switch (datatype)
            {
                case EnumeratedType.DATE_TIME:
                    result = "DateTime";
                    break;

                case EnumeratedType.CHAR:
                    result = "Char";
                    break;

                case EnumeratedType.DECIMAL:
                    result = "Decimal";
                    break;

                case EnumeratedType.DOUBLE:
                    result = "Double";
                    break;

                case EnumeratedType.INT32:
                    result = "Int32";
                    break;

                case EnumeratedType.STRING:
                    result = "String";
                    break;

                case EnumeratedType.AUTO_INT:
                    result = "AutoInt";
                    break;

                default:
                    result = "UNKNOWN_DATA_TYPE";
                    break;
            }

            return result;
        }
    }
}
